package com.himaci.gtbattle.model;

import java.util.ArrayList;

/**
 * Kelas world
 *
 * @author XNPSDN
 */
public class World {

    public static final int STATE_NORMAL = 0;
    public Player player1;
    public Player player2;
    public int state;
    public float stateTime;
    public ArrayList<Projectile> projectile;
    public float projectileTime;
    public int advanceCounter;

    public class Projectile {

	public static final float PROJECTILE_TIME = 1.0f;
	public int startPlayerID;
	public int startCharID;
	public int targetPlayerID;
	public int targetCharID;

	public Projectile(int sP, int sC, int tP, int tC) {
	    startPlayerID = sP;
	    startCharID = sC;
	    targetPlayerID = tP;
	    targetCharID = tC;
	}
    }

    /**
     * Konstruktor
     */
    public World() {
	// nothing todo here...
    }

    /**
     * Konstruktor
     */
    public World(int p1AiLevel, int p2AiLevel) {
	player1 = new Player(Player.PLAYER_ONE, p1AiLevel);
	player2 = new Player(Player.PLAYER_TWO, p2AiLevel);
	state = STATE_NORMAL;
	stateTime = 0;
	advanceCounter = 0;
	
	// ga penting dicopy
	projectile = new ArrayList<>();
	projectileTime = 0;
    }

    /**
     * Mengkopi world
     * @return World baru dengan isian yang telah dikopi
     */
    public World copy() {
	World retVal = new World();

	retVal.player1 = player1.copy();
	retVal.player2 = player2.copy();
	retVal.state = state;
	retVal.stateTime = stateTime;
	retVal.advanceCounter = advanceCounter;

	return retVal;
    }

    /**
     * Update the world
     * @param deltaTime Selisih waktu
     */
    public void update(float deltaTime) {
	player1.update(deltaTime);
	player2.update(deltaTime);
	stateTime += deltaTime;
    }

    /**
     * Apakah world sudah idle
     * @return Idle apa kagak
     */
    public boolean isReady() {
	for (int i = 0; i < 3; ++i) {
	    if (!player1.characters[i].isReady()
		    || !player2.characters[i].isReady()) {
		return false;
	    }
	}
	return true;
    }

    /**
     * Animasi attack otomatis setelah tiap turn
     */
    public void animAdvance() {
	// iterasi seluruh karakter player 1	
	for (int i = 0; i < 3; ++i) {
	    if (!player1.characters[i].isDead()) {
		// iterasi seluruh karakter target
		for (int j = 0; j < 3; ++j) {		    
		    int targetCharID = (j + advanceCounter) % 3;
		    if (!player2.characters[targetCharID].isDead()) {
			// animasi yang ini
			// player1.characters[i].attack(player2.characters[targetCharID]);			
			projectile.add(new Projectile(1, i, 2, targetCharID));
			player1.characters[i].animAttack();
			break;
		    }
		}
	    }

	    if (!player2.characters[i].isDead()) {
		// iterasi seluruh karakter target
		for (int j = 0; j < 3; ++j) {
		    int targetCharID = (j + advanceCounter) % 3;
		    if (!player1.characters[targetCharID].isDead()) {
			// animasi yang ini
			// player1.characters[i].attack(player2.characters[targetCharID]);	
			projectile.add(new Projectile(2, i, 1, targetCharID));
			player2.characters[i].animAttack();
			break;
		    }
		}
	    }
	}
    }
    
    /**
     * Clear animasi projectile
     */
    public void clearProjectile() {
	projectile.clear();
	projectileTime = 0;
    }

    /**
     * Attack otomatis setelah tiap turn
     */
    public void advance() {
	// jumlah penambahan energy setiap ganti giliran
	int energyAmmount = 5;
	// iterasi seluruh karakter player 1	
	for (int i = 0; i < 3; ++i) {
	    if (!player1.characters[i].isDead()) {
		// iterasi seluruh karakter target
		for (int j = 0; j < 3; ++j) {
		    int targetCharID = (j + advanceCounter) % 3;
		    if (!player2.characters[targetCharID].isDead()) {
			player1.characters[i].attack(player2.characters[targetCharID]);
			break;
		    }
		}
		// check buff
		if (player1.characters[i].buffCounter > 0) {
		    player1.characters[i].buffCounter--;
		}
		if (player1.characters[i].buffCounter == 0) {
		    if (player1.characters[i].buff == GameChar.BUFF_CURSED) {
			player1.characters[i].removeCursed();
		    }
		    if (player1.characters[i].buff == GameChar.BUFF_SILENT) {
			player1.characters[i].removeSilent();
		    }
		}
		// tambah mana
		player1.characters[i].currEnergy += energyAmmount;
		if (player1.characters[i].currEnergy > player1.characters[i].maxEnergy) {
		    player1.characters[i].currEnergy = player1.characters[i].maxEnergy;
		}
	    }

	    if (!player2.characters[i].isDead()) {
		// iterasi seluruh karakter target
		for (int j = 0; j < 3; ++j) {
		    int targetCharID = (j + advanceCounter) % 3;
		    if (!player1.characters[targetCharID].isDead()) {
			player2.characters[i].attack(player1.characters[targetCharID]);
			break;
		    }
		}
		// check buff
		if (player2.characters[i].buffCounter > 0) {
		    player2.characters[i].buffCounter--;
		}
		if (player2.characters[i].buffCounter == 0) {
		    if (player2.characters[i].buff == GameChar.BUFF_CURSED) {
			player2.characters[i].removeCursed();
		    }
		    if (player2.characters[i].buff == GameChar.BUFF_SILENT) {
			player2.characters[i].removeSilent();
		    }
		}
		// tambah mana
		player2.characters[i].currEnergy += energyAmmount;
		if (player2.characters[i].currEnergy > player2.characters[i].maxEnergy) {
		    player2.characters[i].currEnergy = player2.characters[i].maxEnergy;
		}
	    }
	}
	advanceCounter++;
    }

    /**
     * Update seluruh karakter yang HP-nya abis menjadi dead
     */
    public void updateDead() {
	for (int i = 0; i < 3; ++i) {
	    if (player1.characters[i].state != GameChar.STATE_DEAD) {
		// iterasi seluruh karakter target
		if (player1.characters[i].currVitality <= 0) {
		    player1.characters[i].state = GameChar.STATE_DEAD;
		    player1.characters[i].stateTime = 0;
		}
	    }
	    if (player2.characters[i].state != GameChar.STATE_DEAD) {
		// iterasi seluruh karakter target
		if (player2.characters[i].currVitality <= 0) {
		    player2.characters[i].state = GameChar.STATE_DEAD;
		    player2.characters[i].stateTime = 0;
		}
	    }
	}
    }

    /**
     * Cek apakah game over atau tidak
     * @return -1 = tidak, 0 = seri, 1 = player 1 menang, 2 = player 2 menang
     */
    public int gameOver() {
	boolean p1Dead = true;
	boolean p2Dead = true;
	for (int i = 0; i < 3; ++i) {
	    if (player1.characters[i].state != GameChar.STATE_DEAD) {
		p1Dead = false;
	    }
	    if (player2.characters[i].state != GameChar.STATE_DEAD) {
		p2Dead = false;
	    }
	}
	// cek siapa yang menang
	if (p1Dead && p2Dead) {
	    return 0;
	} else if (!p1Dead && p2Dead) {
	    return 1;
	} else if (p1Dead && !p2Dead) {
	    return 2;
	}
	return -1;
    }

    /**
     * Print out data world
     */
    public void display() {
	// print state character
	for (int i = 0; i < 3; ++i) {
	    System.out.print("P1: C" + i + "(" + player1.characters[i].state + "): Vit = " + player1.characters[i].currVitality);
	    System.out.print("\t| Mana = " + player1.characters[i].currEnergy);
	    System.out.print("\t| Atk = " + player1.characters[i].getAttack());
	    System.out.print("\t| Def = " + player1.characters[i].currDefense);
	    System.out.print("\t| Buff = " + player1.characters[i].buff);
	    System.out.println("\t| BuffCount = " + player1.characters[i].buffCounter);
	}
	System.out.println("");
	for (int i = 0; i < 3; ++i) {
	    System.out.print("P2: C" + i + "(" + player2.characters[i].state + "): Vit = " + player2.characters[i].currVitality);
	    System.out.print("\t| Mana = " + player2.characters[i].currEnergy);
	    System.out.print("\t| Atk = " + player2.characters[i].getAttack());
	    System.out.print("\t| Def = " + player2.characters[i].currDefense);
	    System.out.print("\t| Buff = " + player2.characters[i].buff);
	    System.out.println("\t| BuffCount = " + player2.characters[i].buffCounter);
	}
	System.out.println("");
    }
}
